#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<ctype.h>
#include<fcntl.h>
#include<sys/stat.h>

#define NUM 64
#define OP_NUM 64
#define DEFAULT 0
#define REOUTPUT 1
#define REAPPEND 2
#define REINPUT 3
#define trimSpace(begin) do{\
  while(isspace(*begin))  begin++;\
}while(0) 

char buff[NUM];
char* commande[OP_NUM];

int exit_sig = 0;
int exit_code = 0;

int RedirType = DEFAULT; 
char* RedirFile = NULL;


int main(){
  while(1){
    printf("用户名@主机名 当前路径#");
    //获取用户输入
    char* tmp = fgets(buff,sizeof(buff)-1,stdin);//fgets meet \n end,then add \0 on end
    buff[strlen(buff)-1]=0;
    assert(tmp);
    //处理输出重定向
    char* begin = buff;
    char* end = buff + strlen(buff);
    while(begin < end){
      if(*begin == '>'){
        *begin = '\0';
        begin++;
        if(*begin == '>'){
          RedirType = REAPPEND;
          begin++;
        }//append
        else{
          RedirType = REOUTPUT;
        }
        trimSpace(begin);
        RedirFile = begin;
        break;
      }
      else if (*begin == '<'){
        RedirType = REINPUT;
        begin++;
        trimSpace(begin);
        RedirFile = begin;
        break;
      }
      begin++;
    }
    //拆分命令
    commande[0] = strtok(buff," ");
    int i = 0;
    while(commande[++i]=strtok(NULL," "));
    //fork execut
    if(strcmp(commande[0],"cd")==0){
      chdir(commande[1]);
      continue;
    }
    if(strcmp(commande[0],"echo")==0){
      if(commande[1] != NULL &&strcmp(commande[1],"$?")==0){
        printf("exit_sig is:%d,exit_code is:%d \n",exit_sig,exit_code);
      }else if (commande[1] != NULL){
        printf("%s\n",commande[1]);
      }
      continue;
    }
    pid_t id = fork();
    if(id == 0){
      switch(RedirType){
        case DEFAULT:
          {
            //
          }
          break;
        case REOUTPUT:
        case REAPPEND:
          { 
            umask(0);
            int flags = O_WRONLY|O_CREAT;
            if(RedirType == REAPPEND) flags |= O_APPEND;
            else flags |= O_TRUNC;
            int fd = open(RedirFile,flags,0666);
            dup2(fd,1);
            
          }
          break;
        case REINPUT:
          {
            int  fd = open(RedirFile,O_RDONLY);
            dup2(fd,0);
          }
          break;
      }
      execvp(commande[0],commande);
      exit(1);
    }
    int status = 0;
    waitpid(id,&status,0 );
    exit_sig = status&0x7f;
    exit_code = (status>>8)&0xff;
  }
//  for(int j = 0 ; j < i ; j++ ){
//    printf("%s\n",commande[j]);
//  } 

  return 0;
}
